
#include <SingleGame.h>
#include <QTimer>



void SingleGame::click(int id,int row,int col)
{
    if(!this->_bRedRun){
        //黑走
        return;
    }
    Board::click(id,row,col);
    if(!this->_bRedRun){
        //保存刚刚人走的一步到开局历史最多200步
        if(regretSteps.size()<=200){
            Step *step;
            step=regretSteps.at(regretSteps.size()-1);
            QString tmp = QString::number(step->_colfrom)+QString::number(step->_rowfrom)+QString::number(step->_colto)+QString::number(step->_rowto);
            history=history+tmp;
        }


        //定时器0.3秒后启动电脑思考
        QTimer::singleShot(400,this,SLOT(computerMove()));
    }
}
void SingleGame::computerMove()
{
    if(isStart==false){
        //游戏未开始或已结束,不移动
        return;
    }
    //先判断开局库
    Step* step;
    if(!isCanJu){
        //搜索开局库
//        step = regretSteps.at(0);
//        QString tmp = QString::number(step->_colfrom)+QString::number(step->_rowfrom)+QString::number(step->_colto)+QString::number(step->_rowto);
        qDebug()<<history;
        QStringList arr;
        int len=history.length();
        QString ls;
        //遍历棋谱
        for (int i=0;i< openList.size();i++){
            ls=openList.at(i);
            if (ls.mid(0,len)==history) {
                arr.append(openList.at(i));
            }
        }
        qDebug()<<"搜索到"<<arr.size();
        if(arr.size()==0){
            step = getBestMove();
        }else{
            //随机取一步走
            qsrand(time(NULL));
            int n = qrand() % arr.size();
            ls=arr.at(n);
            qDebug()<<ls;
            ls=ls.mid(len,4);
            history=history+ls;
            step=new Step;
            step->_colfrom = int(ls.at(0).toLatin1())-'0';
            step->_rowfrom = int(ls.at(1).toLatin1())-'0';
            step->_colto = int(ls.at(2).toLatin1())-'0';
            step->_rowto = int(ls.at(3).toLatin1())-'0';
            step->_moveid = getPieceId(step->_rowfrom,step->_colfrom);
            step->_killid = getPieceId(step->_rowto,step->_colto);
//            qDebug()<<ls;
        }
    }else{
        //判断残局库
//        qDebug()<<"残局"<<history;
        int len=history.length();
        QString ls;
        if (moveList.size()>len && moveList.mid(0,len)==history) {
            ls=moveList.mid(len,4);
            history=history+ls;
            qDebug()<<moveList<<history;
            step=new Step;
            step->_colfrom = int(ls.at(0).toLatin1())-'0';
            step->_rowfrom = int(ls.at(1).toLatin1())-'0';
            step->_colto = int(ls.at(2).toLatin1())-'0';
            step->_rowto = int(ls.at(3).toLatin1())-'0';
            step->_moveid = getPieceId(step->_rowfrom,step->_colfrom);
            step->_killid = getPieceId(step->_rowto,step->_colto);
            qDebug()<<ls<<step->_moveid<<step->_killid;
        }else{
            history=history+"-";
            step = getBestMove();
        }
    }

//    Step* step = getBestMove();
    if(step!=NULL){
        //计算着法
        QString moveName = getMoveName(step);
        qLog("电脑:"+moveName);
        //end
//        lastStep=step;
        //先保存再移动
        saveStep(step->_moveid,step->_killid,step->_rowto,step->_colto,regretSteps);
//        qDebug()<<step->_moveid<<"吃"<<step->_killid<<"row from"<<step->_rowfrom<<"col from"<<step->_colfrom<<"row to"<<step->_rowto<<"col to"<<step->_colto;
        movePiece(step->_moveid,step->_killid,step->_rowto,step->_colto);
        //判断将是否被吃掉
        if(step->_killid!=-1&&_p[step->_killid]._type==Piece::JIANG){
            gameOver();
        }
    }
//    qDebug()<<"所有步数:"<<regretSteps.count();
    update();
}
Step* SingleGame::getBestMove()
{
    /*
     * 1.看看有哪些步骤可以走
     * 2.尝试去走
     * 3.评估走完后的结果
     * 4.取最好的结果来走
    */
    //得到所有可以走的步骤
    QVector<Step*> steps;
    getAllPossibleMove(steps);
    qDebug()<<"所有步数:"<<steps.count();
//    qDebug()<<"当前局面分:"<<calcScore();
//    return NULL;
    //尝试走一下
    //初始化局面分
    int maxScore = -9999999;
    Step* ret=NULL;
    while(steps.count())
    {
        //qDebug()<<steps.count();
        Step* step=steps.back();
        steps.removeLast();

        fakeMove(step);
        //走完一步后计算红棋最可能走的一步 也就是红棋让黑棋的局面分尽量少
        int score=getMinScore(_level-1,maxScore);
        unfakeMove(step);
//        qDebug()<<"局面分:"<<score;
        if(score > maxScore){
            maxScore=score;
            if(ret){
                delete ret;
            }
            ret=step;
        }else{
            delete step;
        }
    }
    qDebug()<<"最好局面分:"<<maxScore;
    //返回最好的一步
    return ret;
}

void SingleGame::getAllPossibleMove(QVector<Step*>& steps)
{
    int min=0,max=16;
    if(this->_bRedRun)
    {
        min=16;
        max=32;
    }
    for(int i=min;i<max;i++)
    {
        if(_p[i]._dead){
            continue;
        }

        for(int row=0;row<=9;row++)
        {
            for(int col=0;col<=8;col++)
            {
                int killid = this->getPieceId(row,col);

                //判断要吃的棋子是否已经被吃
                //要注意killid为-1的情况
                if(killid!=-1&&_p[killid]._dead){
                    continue;
                }

                //qDebug()<<killid<<i<<sameColor(killid,i);
                //颜色相同 跳过
                if(sameColor(killid,i)){
                    continue;
                }

//                qDebug()<<"开始处理"<<canMove(i,row,col,killid);

                if(canMove(i,row,col,killid))
                {
//                    if(i==15)
//                    qDebug()<<i<<row<<col<<killid;
                    //能移动的保存起来
                    saveStep(i,killid,row,col,steps);
                }
            }
        }
    }

}

void SingleGame::fakeMove(Step* step)
{
    killPiece(step->_killid);
    movePiece(step->_moveid,step->_rowto,step->_colto);
}
void SingleGame::unfakeMove(Step* step)
{
    revivePiece(step->_killid);
    movePiece(step->_moveid,step->_rowfrom,step->_colfrom);
}
int SingleGame::calcScore()
{
    int redScore=0,blackScore=0;
    //{JIANG,CHE,PAO,MA,BING,SHI,XIANG}
    static int chessScore[]={10000,500,300,200,50,20,20};

    //黑棋的分数
    for(int i=0;i<16;i++)
    {
        if(_p[i]._dead)continue;
//        blackScore+=chessScore[_p[i]._type];
        blackScore+=getPieceScore(i);
    }
    //红棋的分数
    for(int i=16;i<32;i++)
    {
        if(_p[i]._dead)continue;
//        redScore+=chessScore[_p[i]._type];
        redScore+=getPieceScore(i);
    }
    //黑棋分的总数 - 红棋分的的总数
    return blackScore-redScore;
}

int SingleGame::getMinScore(int level,int maxScore)
{
    if(level==0){
        return calcScore();
    }
    //获得红棋的最小
    QVector<Step*> steps;
    getAllPossibleMove(steps);
    int minScore=999999;
    while(steps.count())
    {
        Step* step=steps.back();
        //删除取出的一步
        steps.removeLast();

        fakeMove(step);
        int score=getMaxScore(level-1,minScore);
        unfakeMove(step);
        //释放step
        delete step;

        //判断将死，撤销这一步
        if(_p[20]._dead){
            return 999999;
        }
        //end

        if(score<=maxScore)
        {
            if(steps.size()!=0){
                steps.remove(0,steps.size());
            }
            return score;
        }

        if(score < minScore){
            minScore=score;
        }
    }
    return minScore;
}
int SingleGame::getMaxScore(int level,int minScore)
{
    if(level==0){
        return calcScore();
    }
    //获得黑棋的最大
    QVector<Step*> steps;
    getAllPossibleMove(steps);
    int maxScore=-999999;
    while(steps.count())
    {
        Step* step=steps.back();
        //删除取出的一步
        steps.removeLast();

        fakeMove(step);
        int score=getMinScore(level-1,maxScore);
        unfakeMove(step);
        //释放step
        delete step;

        //判断将死，撤销这一步
        if(_p[4]._dead){
            return -999999;
        }
        //end

        if(score>=minScore)
        {
            if(steps.size()!=0){
                steps.remove(0,steps.size());
            }
            return score;
        }

        if(score > maxScore){
            maxScore=score;
        }
    }
    return maxScore;
}
void SingleGame::StartClick()
{
    _bSide=false;
    isStart=true;
    history="";
    startButton->setEnabled(false);
    qLog("系统:开始游戏");
    regretButton->setEnabled(true);

    startButton->setStyleSheet("border:1px solid gray;font: 14pt \"楷体\";color: gray;font-weight: bold;border-image: url(:/img/btn-bg.png);");
    regretButton->setStyleSheet("border:1px solid gray;font: 14pt \"楷体\";color: rgb(85, 255, 0);font-weight: bold;border-image: url(:/img/btn-bg.png);");
}
void SingleGame::RegretClick()
{
    if(regretSteps.size()<2){
        qLog("系统:没有棋可悔");
        return;
    }
    qLog("系统:开始悔棋");
    //取出步数
    Step *step;
    step = regretSteps.back();
    regretSteps.removeLast();
    //复活棋子
    revivePiece(step->_killid);
    movePiece(step->_moveid,step->_rowfrom,step->_colfrom);
    qDebug()<<"悔棋"<<step->_moveid<<"吃"<<step->_killid<<"row from"<<step->_rowfrom<<"col from"<<step->_colfrom<<"row to"<<step->_rowto<<"col to"<<step->_colto;
    step = regretSteps.back();
    regretSteps.removeLast();
    //复活棋子
    revivePiece(step->_killid);
    movePiece(step->_moveid,step->_rowfrom,step->_colfrom);
    //走棋记录处理
    if(history.length()<=8){
        history="";
    }else{
        history=history.mid(0,history.length()-8);
    }
    update();
}
void SingleGame::isShowButton(bool isShow)
{

}
void SingleGame::initGame()
{
    QString displayString;
    QFile file(":/res/openLibAll.pu");
    if(!file.open(QIODevice::ReadOnly | QIODevice::Text))
    {
        qDebug()<<"Can't open the file!"<<endl;
    }
    qDebug()<<"开始读取";
    QByteArray line = file.readLine();
    displayString=QString(line);
    file.close();
    openList=displayString.split(" ");
    qDebug()<<"开局库"<<openList.at(0)<<"。";
}
void SingleGame::startCanJu()
{
    isCanJu=true;
    qDebug()<<"初始化残局"<<location<<moveList;
    this->setWindowTitle(puName);
    qLog("系统:游戏目标->"+result);
    for (int i=0;i<32;i++) {
        _p[i]._dead=true;
    }
    QString ls1,ls2;
    for(int i=0,j=0;i<location.length();i=i+2)
    {
        ls1=location.at(i);
        if(ls1=="9"){
            continue;
        }
        ls2=location.at(i+1);
        j=i/2<16?i/2+16:i/2-16;
        _p[j]._dead=false;
        _p[j]._x=ls2.toInt();
        _p[j]._y=ls1.toInt();
//        qDebug()<<ls1<<ls2;
    }
    update();
}
void SingleGame::AgainClick()
{
    Board::AgainClick();
    if(isCanJu){
        startCanJu();
    }
}

int SingleGame::getPieceScore(int id)
{
//    return 0;
    int x,y;
    if(_p[id]._red){
        x=_p[id]._x;
        y=_p[id]._y;
    }else{
        x=9-_p[id]._x;
        y=8-_p[id]._y;
    }
    x=_p[id]._x;
    y=_p[id]._y;
//    qDebug()<<x<<y;
    switch (_p[id]._type) {
    case Piece::JIANG:
        return J[x][y];
        break;
    case Piece::SHI:
        return S[x][y];
        break;
    case Piece::CHE:
        return C[x][y];
        break;
    case Piece::MA:
        return M[x][y];
        break;
    case Piece::PAO:
        return P[x][y];
        break;
    case Piece::XIANG:
        return X[x][y];
        break;
    case Piece::BING:
        return Z[x][y];
        break;
    }
    qDebug()<<"sadas";
    return 0;
}
